package com.sne.common.aspect;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sne.common.entity.Result;
import com.sne.common.util.IdGeneratorUtil;
import com.sne.sys.entity.SysLog;
import com.sne.sys.entity.SysUser;
import com.sne.sys.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import nl.bitwalker.useragentutils.UserAgent;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * <p>
 * 日志处理AOP
 * </p>
 *
 * @author fanghh
 * @since 2020/1/10
 */
@Slf4j
@Component
@Aspect
public class LogAspect {

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private KafkaTemplate kafkaTemplate;


    /**
     * 异常
     */
    private static final String ERROR = "失败";

    /**
     * 正常
     */
    private static final String SUCCESS = "成功";


    @Pointcut(value = "execution(* com.sne.*.controller.*.*(..)) && " +
            "!execution(* com.sne.sys.controller.SysLogController.*(..)) && " +
            "!execution(* com.sne.sys.controller.LoginController.*(..))")
    public void pointCut() {
    }

    @Transactional(rollbackFor = Exception.class)
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void afterTrowing(JoinPoint joinPoint,Throwable e) {
        saveLog(joinPoint, ERROR,Result.failed(e.getMessage(), e));
    }

    @Transactional(rollbackFor = Exception.class)
    @AfterReturning(value = "pointCut()",returning = "value")
    public void after(JoinPoint joinPoint,Object value) {
        saveLog(joinPoint, SUCCESS,value);
    }

    private void saveLog(JoinPoint joinPoint, String success,Object data) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation annotation = method.getAnnotation(ApiOperation.class);

        SysLog sysLog = new SysLog();
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        SysUser user = iSysUserService.getCurrentUser();
        sysLog.setId(IdGeneratorUtil.incrementId())
                .setTitle(annotation.value())
                .setState(success)
                .setRequestType(request.getMethod())
                .setIp(request.getRemoteAddr())
                .setCreateUserName(user.getUserName())
                .setCreateTime(LocalDateTime.now())
                .setClientName(userAgent.getBrowser().getName())
                .setRequestParams(JSONArray.toJSONString(joinPoint.getArgs()))
                .setResponse(JSONObject.toJSONString(data));
        try{
            kafkaTemplate.sendDefault(JSONObject.toJSONString(sysLog));
        }catch (Exception e){
            log.error("kafka生产异常:",e);
        }
    }



}
